/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../helper_pass_through/head.h"
#include "../tools/head.h"
#include "../xos/head.h"
#include "../msg/head.h"
#include "state.h"
#include "hook.h"
#include "msg.h"
#include "mgr.h"

namespace jsp
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 

    typedef xos_stl::auto_list< xos::i_msg, thread_lock > MSG_LIST;

	static xos::i_event * event_ptr = 0;
    static MSG_LIST * msg_list_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 

    mgr::mgr()
    {
    }

    mgr::~mgr()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::notify( xos::i_msg *& pMsg, bool bPassThrough )
    {
        int ret = 0;
        if( bPassThrough )
        {
            helper_pass_through obj;
            obj.push( pMsg );
        }
        pMsg->set_runnable( 0, msg::on_msg );
        msg_list_ptr->lock();
        msg_list_ptr->push_back( pMsg );
        msg_list_ptr->un_lock();
        event_ptr->set_event();
        pMsg = 0;
        return ret;
    }

    xos_container::i_container * mgr::xos()
    {
        return os::get();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::run( int argc, const char  * argv[] )
    {
        bool bHasMore = false;

        {
            init( argc, argv );
        }
        while( !state::stopped() )
        {
            if( !bHasMore )
            {
                event_ptr->wait( xos::i_event::EVENT_WAIT_INFINITE );
            }
            bHasMore = proc();
        }
        {
            term();
        }

        return 0;
    } 

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    bool mgr::proc()
    {
        bool bHasMore = true;

        xos::i_msg * pMsg = 0;
        {
            msg_list_ptr->lock();
            if( msg_list_ptr->size() > 0 )
            {
                pMsg = msg_list_ptr->front();
                msg_list_ptr->pop_front();
            }
            msg_list_ptr->un_lock();
        }
        if( pMsg )
        {
            xos::f_runnable pRun = pMsg->get_runnable( 0, 0 );
            pRun( pMsg );
        }
        else
        {
            bHasMore = false;
        }

        return bHasMore;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::init( int argc, const char  * argv[] )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = hook::init();
        }

        if( 0 == ret )
        {
            ret = mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_EVENT, (void **)&event_ptr );
        }

        if( 0 == ret )
        {
            ret = xos_stl::init_list( msg_list_ptr );
        }

        if( 0 == ret )
        {
            state::set_running();
        }

        if( 0 == ret )
        {
            xos::i_msg * pMsg = mgr::xos()->msg();
            pMsg->set_void( 0, argv );
            pMsg->set_int( 1, argc );
            msg::notify( pMsg, MSG_TYPE_WORK, false );
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;

        xos_stl::term_list( msg_list_ptr, true );
        xos_stl::release_interface( event_ptr );
        hook::term();

        return ret;
    }

} // xos
